/*
 *  modifier: Honrun
 *  date:     2023/10/29 20:42
 */
#include "stdio.h"
#include "microCPU.h"
#include "microTime.h"
#include "microList.h"
#include "microTask.h"
#include "microDelay.h"


/* 延时链表 */
MrListType g_typeMrListDelay = {&g_typeMrListDelay, &g_typeMrListDelay};


/* 延时 n Tick */
void vMrDelayTick(int64_t *plTickLast, int64_t lTick)
{
    MrTaskType *ptypeTaskNow = (MrTaskType *)g_ptypeMrTaskCurrent;

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 从就绪、事件链表中移除 */
    cMrListRemove(&ptypeTaskNow->list);

    /* 从延时链表中移除 */
    cMrListRemove(&ptypeTaskNow->listDelay);

    /* 计算延时 Tick 数量 */
    if(plTickLast != NULL)
    {
        *plTickLast += lTick;
        ptypeTaskNow->listDelay.value = *plTickLast;
    }
    else
    {
        ptypeTaskNow->listDelay.value = lMrTickGet() + lTick;
    }

    /* 插入到延时链表 */
    cMrListInsert(&g_typeMrListDelay, &ptypeTaskNow->listDelay);

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发任务切换 */
    vMrCpuYield();
}

/* 延时 n 毫秒 */
void vMrDelayMs(int64_t *plTickLast, int64_t lTime)
{
    lTime /= (int64_t)(1000 / configMr_RTOS_CLOCK_HZ);

    vMrDelayTick(plTickLast, lTime);
}

/* 判断延时事件是否溢出 */
void vMrDelayCheck(void)
{
    MrListType *ptypeListNow = NULL;
    MrTaskType *ptypeTaskNow = NULL;
    int64_t lTime = lMrTickGet();

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 把遍历指针指向就绪链表首部 */
    while((ptypeListNow = g_typeMrListDelay.pNext) != &g_typeMrListDelay)
    {
        /* 排序存储，第一个不满足，后面的也不会满足 */
        if(lTime < ptypeListNow->value)
            break;

        ptypeTaskNow = (MrTaskType *)ptypeListNow->pElement;

        /* 从延时链表中移除 */
        cMrListRemove(&ptypeTaskNow->listDelay);

        /* 从事件链表中移除 */
        cMrListRemove(&ptypeTaskNow->list);

        /* 插入到就绪链表 */
        ptypeTaskNow->list.value = ptypeTaskNow->priority;
        cMrListInsert(&g_typeMrListTaskReady, &ptypeTaskNow->list);
    }

    /* 退出临界段 */
    vMrCpuEnableIsr();
}
